﻿using System;
using NJabber.Client;
using NJabber.Client.StanzaFactories;
using NJabber.Stream.Elements;

namespace NJabber
{
    public class PresenceStanzaHandler : IStanzaHandler<PresenceStanza>
    {
        private IPresenceStatusUpdater presenceUpdater;
        private IPresenceSubscriptionRegistry subscriptionRegistry;

        public PresenceStanzaHandler(IPresenceStatusUpdater presenceUpdater, IPresenceSubscriptionRegistry subscriptionRegistry)
        {
            this.presenceUpdater = presenceUpdater;
            this.subscriptionRegistry = subscriptionRegistry;
        }

        public bool ProcessStanza(XmppClientRuntime context, PresenceStanza stanza)
        {
            if (stanza == null) throw new ArgumentNullException("stanza");
            if (IsPresenceNotification(stanza)) UpdatePresence(stanza);
            if (IsSubscriptionRequest(stanza)) subscriptionRegistry.RegisterInboundRequest(stanza.From);
            if (IsSubscriptionApproveResponse(stanza)) subscriptionRegistry.OutboundRequest(stanza.From).Approve();
            if (IsSubscriptionDenyResponse(stanza)) subscriptionRegistry.OutboundRequest(stanza.From).Deny();
            return true;
        }

        private void UpdatePresence(PresenceStanza stanza)
        {
            bool isAvailable = string.IsNullOrEmpty(stanza.Type);
            AvailabilityStatus status = ConvertHelper.StringToAvailabilityStatus(stanza.Availability);
            presenceUpdater.UpdatePresence(stanza.From, isAvailable, status, stanza.StatusText);
        }

        private bool IsPresenceNotification(PresenceStanza stanza)
        {
            return stanza.Type == PresenceStanzaType.Unavailable || string.IsNullOrEmpty(stanza.Type);
        }

        private bool IsSubscriptionRequest(PresenceStanza stanza)
        {
            return stanza.Type == PresenceStanzaType.Subscribe;
        }

        private bool IsSubscriptionDenyResponse(PresenceStanza stanza)
        {
            return stanza.Type == PresenceStanzaType.Unsubscribed;
        }

        private bool IsSubscriptionApproveResponse(PresenceStanza stanza)
        {
            return stanza.Type == PresenceStanzaType.Subscribed;
        }
    }
}
